<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="description" content="">
    <meta name="author" content="">
    <link rel="shortcut icon" href="../../docs-assets/ico/favicon.png">

    <title>p2pool - node stats</title>

    <link href="https://fonts.googleapis.com/css?family=Roboto:300,300italic,400,400italic,100,100italic,500,500italic,700,700italic,900,900italic" rel="stylesheet" type="text/css">
    <link href='https://fonts.googleapis.com/css?family=Roboto+Condensed:400italic,700italic,400,700' rel='stylesheet' type='text/css'>

    <!-- Bootstrap core CSS -->
    <link rel="stylesheet" href="css/bootstrap.min.css">
    <link rel="stylesheet" href="css/bootstrap-theme.min.css">
    <link href="https://netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet">

    <script src="js/jquery-2.0.3.min.js"></script>
    <script src="js/bootstrap.min.js"></script>
    <script src="js/jquery-dateFormat.min.js"></script>

    <script src="js/highcharts.js"></script>
    <script src="js/exporting.js"></script>

    <script src="js/util.js"></script>
    <script src="js/charts.js"></script>

    <script src="js/config.json"></script>

    <!-- Custom styles for this template -->
    <link href="grid.css" rel="stylesheet">

    <style type="text/css">
      body {
        font-family: 'Roboto', Helvetica, sans-serif;
        font-size: 13px;
      }
      #myModal .modal-dialog {
        width: 70%;/* your width */
      }
    </style>

    <!-- Just for debugging purposes. Don't actually copy this line! -->
    <!--[if lt IE 9]><script src="../../docs-assets/js/ie8-responsive-file-warning.js"></script><![endif]-->

    <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
    <!--[if lt IE 9]>
      <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
      <script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
    <![endif]-->
  </head>

  <body>
    <div id='ribbon' style='display:none;'>
      <a href="https://github.com/johndoe75/p2pool-node-status">
        <img style="position: absolute; top: 0; right: 0; border: 0;" src="img/forkme_right_orange_ff7600.png" alt="Fork me on GitHub">
      </a>
    </div>

    <div id="navbar"></div>

    <div class="container">
      <div class="page-header">
        <h1>p2pool <span id='currency'></span> &dash; node dashboard</h1>
        <b>
          <small>
            <span id='_node' class='hidden'>Node: </span>
            <span id='node' class='hidden'></span><br/>
            Updated: <span id='updated'></span>
          </small>
        </b>
      </div>

      <div id='node_alerts' class="alert alert-danger hidden"></div>

      <!-- We should have a possiblity showing other miners on our node what
           happened or if we have other things to tell them. -->
      <div class="alert alert-info hidden">
        <p><b>2013-12-13: This is a message to miners on my node telling them something really cool.</b></p>
      </div>

      <center>
        <div class='container'>
          <button id='hour' type="button" class="hashrate btn btn-info">Hour</button>
          <button id='day' type="button" class="hashrate btn btn-info">Day</button>
          <button id='week' type="button" class="hashrate btn btn-info">Week</button>
          <button id='month' type="button" class="hashrate btn btn-info">Month</button>
          <button id='year' type="button" class="hashrate btn btn-info">Year</button>
        </div>
      </center>
      <div id='chart'></div>

      <h4>Status</h4>
      <table id='status' class="table table-hover" border='0'>
        <tr>
          <td width='19%'>Local rate:</td>
          <td width='31%' class='text-right'><span id='local_rate'></span></td>
          <td width='19%'>Shares:</td>
          <td width='31%' class='text-right'><span id='shares'></span></td>
        </tr>
        <tr>
          <td width='19%'>Global pool rate:</td>
          <td width='31%' class='text-right'><span id='global_rate'></span></td>
          <td width='19%'>Share difficulty:</td>
          <td width='31%' class='text-right'><span id='share_difficulty'></span></td>
        </tr>
        <tr>
          <td width='19%'>Current block value:</td>
          <td width='31%' class='text-right'><span id='block_value'></span></td>
          <td width='19%'>Expected time to share:</td>
          <td width='31%' class='text-right'><span id='expected_time_to_share'></span></td>
        </tr>
        <tr>
          <td width='19%'>Payout if a block were found NOW:</td>
          <td width='31%' class='text-right'><span id='payout_now'></span></td>
          <td width='19%'>Expected time to block:</td>
          <td width='31%' class='text-right'><span id='expected_time_to_block'></span></td>
        </tr>
        <tr>
          <td width='19%'>Node peers:</td>
          <td width='31%' class='text-right'>
            <i class='fa fa-sign-in fa-fw'></i>
            <span id='peers_in'></span>
            /
            <i class='fa fa-sign-out fa-fw'></i>
            <span id='peers_out'></span>
          </td>
          <td width='19%'>Node uptime:</td>
          <td width='31%' class='text-right'><span id='node_uptime'></span></td>
        </tr>
        <tr>
          <td width='19%'>Node p2pool version:</td>
          <td width='31%' class='text-right'><span id='p2pool_version'></span></td>
          <td width='19%'>Protocol version:</td>
          <td width='31%' class='text-right'><span id='protocol_version'></span></td>
        </tr>
        <tr>
          <td width='19%'>Node fee:</td>
          <td width='31%' class='text-right'><span id='node_fee'></span></td>
          <td width='19%'>Node donation:</td>
          <td width='31%' class='text-right'><span id='node_donation'></span></td>
        </tr>
      </table>

      <h4>Active miners on this node</h4>
      <table id='active_miners' class="table table-hover">
        <tr>
          <th width='50%' class='text-left'>Bitcoin Address</th>
          <th width='12%' class='text-right'>Hashrate</th>
          <th width='12%' class='text-right'>DOA Hashrate</th>
          <th width='12%' class='text-right'>DOA %</th>
          <th width='14%' class='text-right'>Predicted payout</th>
        </tr>
      </table>

<!--
      <h4>Pool Shares</h4>
      <table id='recent_shares' class="table table-hover">
        <tr>
          <th width='50%' class='text-left'>Date/Time</th>
          <th width='15%' class='text-right'>Number</th>
          <th width='15%' class='text-right'>Hash</th>
          <th width='20%' class='text-right'>Confirmations</th>
        </tr>
      </table>
 -->

      <h4>Recent blocks</h4>
      <table id='recent_blocks' class="table table-hover">
        <tr>
          <th>Date/Time</th>
          <th>Number</th>
          <th>Hash</th>
          <th>Confirmations</th>
        </tr>
      </table>
    </div> <!-- /container -->

    <div id='footer'>
      <div class='container'>
        <hr>
        <p class='text-center'>
          Interface by johndoe75
          &dash;
          <a href="https://github.com/johndoe75/p2pool-node-status.git">https://github.com/johndoe75/p2pool-node-status.git</a>
        </p>
        <p class='text-center'>
          Donate some coins, if you like it <code>1MzFr1eKzLEC1tuoZ7URMB7WWBMgHKimKe</code>
          (<i class='fa fa-btc'></i>) or <code>LSRfZJf75MtwzrbAUfQgqzdK4hHpY4oMW3</code> (LTC)
        </p>
      </div>
    </div>
    <script type="text/javascript">

    $(document).ready(function() {
      // shall the Github ribbon been shown?
      if(config.show_github_ribbon) { $('#ribbon').fadeIn(1000); }
      else { $('#ribbon').remove(); }

      $(document).trigger('init');
      if(config.navbar_url && config.navbar_url.length > 0) {
        $("#navbar").load(config.navbar_url);
      }
    });

    var currency, currency_info, rate, local_stats,
        global_stats, current_payouts, recent_blocks,
        payout_addr;
    var local_hashrate= 0, local_doa_hashrate= 0;

    var jsonp= "./jsonp.php?callback=?";

    var api_url= "";

    // Check if we shall remotely connect to a p2pool running somewhere

    if(config.host && config.host.length > 0) {
      api_url= jsonp + '&host=' + encodeURI(config.host) + '&report=';
      $('#node').removeClass('hidden').text(config.host);
      $('#_node').removeClass('hidden');
    }

    // ==================================================================
    // event handlers

    // toggle hashrate chart

    $('#hour.hashrate').click(function(e) {
      fetchGraph('hour');
    });
    $('#day.hashrate').click(function(e) {
      fetchGraph('day');
    });
    $('#week.hashrate').click(function(e) {
      fetchGraph('week');
    });
    $('#month.hashrate').click(function(e) {
      fetchGraph('month');
    });
    $('#year.hashrate').click(function(e) {
      fetchGraph('year');
    });

    // ==================================================================
    // custom event handlers

    // init

    $(document).on('init', function(e, eventInfo) {
      fetchdata();
      fetchBlocks(); /*fetchShares();*/
      fetchGraph('day'); /*fetchPeers();*/
    });

    $(document).on('update', function(e, eventInfo) {
      fetchdata();
      fetchBlocks();
    });

    $(document).on('update_graph', function(e, eventInfo) {
      console.log(chart.title.text);
      graphPeriod= chart.title.text.match(/\((.+)\)/)[1] || 'day';
      fetchGraph(graphPeriod);
    });

    // Fills the list of active miners on this node.  I know, there are
    // zillions of people out there on p2pool.  But I'm typically only
    // interested to see, who is mining on my node.

    $(document).on('update_miners', function(e, eventInfo) {
      local_hashrate= 0; local_doa_hashrate= 0;
      $.each(local_stats.miner_hash_rates, function(address, hashrate) {
        tr= $('<tr/>').attr('id', address);

        // highlight our miner if configured
        if(config.myself && config.myself.length > 0 &&
           $.inArray(address, config.myself) >= 0) {
          tr.addClass('warning');
        }

        // highlight the pool's payout address
        payout_addr in current_payouts ?
          $('#payout_now')
            .text(current_payouts[payout_addr])
            .append(' ')
            .append(currency.clone()) :
          $('#payout_now').html('&dash;');

        address_span= $('<span/>').addClass('coin_address').text(address);
        link_icon= $('<i/>').addClass('fa fa-external-link fa-fw');
        blockinfo= $('<a/>')
          .attr('href', currency_info.address_explorer_url_prefix + address)
          .attr('target', '_blank').append(link_icon);

        doa= local_stats.miner_dead_hash_rates[address] || 0;
        doa_prop= (parseFloat(doa) / parseFloat(hashrate)) * 100;

        local_hashrate+= hashrate || 0;
        local_doa_hashrate+= doa  || 0;

        tr.append($('<td/>').addClass('text-left')
          .append(address_span)
          .append('&nbsp;')
          //.append(chart_icon)
          .append(blockinfo));
        tr.append($('<td/>').addClass('text-right')
          .append(formatHashrate(hashrate)));
        tr.append($('<td/>').addClass('text-right')
          .append(formatHashrate(doa)));
        tr.append($('<td/>').addClass('text-right')
          .append(doa_prop.toFixed(2) + '%'));

        payout= current_payouts[address] || 0;

        if(payout) {
          td= $('<td/>').attr('class', 'text-right')
            .text(parseFloat(payout).toFixed(8))
            .append(' ').append(currency.clone());
          tr.append(td);
        }
        else {
          tr.append($('<td/>').attr('class', 'text-right')
            .append($('<i/>').append('no shares yet')));
        }
        $('#'+address).remove(); $('#active_miners').append(tr);
      });

      if(local_doa_hashrate !== 0 && local_hashrate !== 0) {
        doa_rate= (local_doa_hashrate / local_hashrate) * 100;
      } else { doa_rate= 0; }

      rate= formatHashrate(local_hashrate)
        + ' (DOA '
        + formatHashrate(local_doa_hashrate)
        + ' / ' + doa_rate.toFixed(2)
        + '%)';
      $('#local_rate').text(rate);

      pool_hash_rate=
        parseInt(global_stats.pool_hash_rate || 0);
      pool_nonstale_hash_rate=
        parseInt(global_stats.pool_nonstale_hash_rate || 0);
      global_doa_rate= pool_hash_rate - pool_nonstale_hash_rate;

      global_rate= formatHashrate(pool_hash_rate)
        + ' (DOA '
        + formatHashrate(global_doa_rate)
        + ' / ' + ((global_doa_rate / pool_hash_rate) * 100).toFixed(2)
        + '%)';
      $('#global_rate').text(global_rate);

      $('#share_difficulty')
        .text(parseFloat(global_stats.min_difficulty).toFixed(2));

      $('#block_value')
        .text(parseFloat(local_stats.block_value).toFixed(8))
        .append(' ').append(currency.clone());

      $('#node_donation')
        .text((local_stats.donation_proportion * 100) + '%');
      $('#node_fee')
        .text(local_stats.fee + '%');
      $('#p2pool_version')
        .text(local_stats.version);
      $('#protocol_version')
        .text(local_stats.protocol_version);

      $('#peers_in').text(local_stats.peers.incoming);
      $('#peers_out').text(local_stats.peers.outgoing);

      $('#node_uptime').text(('' + local_stats.uptime).formatSeconds());

      if(local_stats.warnings.length > 0) {
        $('#node_alerts').empty();

        $.each(local_stats.warnings, function(key, warning) {
          $('#node_alerts').append($('<p/>').append(warning));
        });

        $('#node_alerts').fadeIn(1000, function() {
          $(this).removeClass('hidden');
        });
      }
      else {
        if(!$('#node_alerts').hasClass('hidden'))
          $('#node_alerts').fadeOut(1000, function() {
            $(this).addClass('hidden');
          });
      }

      $('#shares')
        .text('Total: ' + local_stats.shares.total
        + ' (Orphan: ' + local_stats.shares.orphan
        + ', Dead: ' + local_stats.shares.dead + ')');

      if(local_hashrate !== 0) {
        time_to_share=
          (parseInt(local_stats.attempts_to_share) / parseInt(local_hashrate));
        $('#expected_time_to_share').text((''+time_to_share).formatSeconds());
      } else {
        $('#expected_time_to_share').html('&dash;');
      }

      attempts_to_block=
        parseInt(local_stats.attempts_to_block || 0);
      time_to_block= attempts_to_block / pool_hash_rate;
      $('#expected_time_to_block').text((''+time_to_block).formatSeconds());
    });

    // Fills the recent block table

    $(document).on('update_blocks', function(e, eventInfo) {
      var table = document.getElementById("recent_blocks");
      for (var i = table.rows.length - 1; i > 0; i--) {
        table.deleteRow(i);
      }
      $.each(recent_blocks, function(key, block) {
        ts= block.ts; num= block.number; hash= block.hash;

        // link to blockchain.info for the given hash
        blockinfo= $('<a/>')
          .attr('href', currency_info.block_explorer_url_prefix + hash)
          .attr('target', '_blank').text(hash);

        tr= $('<tr/>').attr('id', num);
        tr.append($('<td/>')
          .append($.format.prettyDate(new Date(ts * 1000))));
        tr.append($('<td/>').append(num));
        tr.append($('<td/>').append(blockinfo));
        tr.append($('<td/>').html('&dash;'));
        $('#'+num).remove(); $('#recent_blocks').append(tr);
      });
    });

    $(document).on('update_shares', function(e, eventInfo) {
      $.each(recent_blocks, function(key, block) {
        ts= block.ts; num= block.number; hash= block.hash;

        // link to blockchain.info for the given hash
        blockinfo= $('<a/>')
          .attr('href', currency_info.block_explorer_url_prefix + hash)
          .attr('target', '_blank').text(hash);

        tr= $('<tr/>').attr('id', num);
        tr.append($('<td/>')
          .append($.format.prettyDate(new Date(ts * 1000))));
        tr.append($('<td/>')
          .append(num));
        tr.append($('<td/>')
          .append(blockinfo));
        tr.append($('<td/>')
          .html('&dash;'));
        $('#recent_blocks').append(tr);
      });
    });

    // Place the currency symbol for the currency the node is mining.  If
    // it's Bitcoin, use the fontawesome BTC icon

    var set_currency_symbol= true;
    $(document).on('update_currency', function(e, eventInfo) {
      if(currency_info.symbol === 'BTC' && config.use_fontawesome) {
        // use fontawesome BTC symbol
        currency= $('<i/>').attr('class', 'fa fa-btc fa-fw');
      }
      else { currency= $('<span/>').append(currency_info.symbol); }

      if(set_currency_symbol) {
        $('#currency')
          .append('(').append(currency).append(')');
        set_currency_symbol= false;
      }
    });

    // Updates the 'Updated:' field in page header

    $(document).on('update_time', function(e, eventInfo) {
      dts= $.format.date(new Date(), 'yyyy-MM-dd HH:mm:ss');
      $('#updated').text(dts);
    });

    // ==================================================================

    var fetchdata= function() {
      $.getJSON(api_url + '/rate', function(data) {
        if(data) rate= data;

        $.getJSON(api_url + '/web/currency_info', function(data) {
          currency_info= data;
          $(document).trigger('update_currency');

          $.getJSON(api_url + '/local_stats', function(data) {
            if(data) local_stats= data;

            $.getJSON(api_url + '/current_payouts', function(data) {
              if(data) current_payouts= data;

              $.getJSON(api_url + '/payout_addr', function(data) {
                if(data) payout_addr= data;

                $.getJSON(api_url + '/global_stats', function(data) {
                  if(data) global_stats= data;
                  $(document).trigger('update_miners');
                  $(document).trigger('update_time');
                });
              });
            });
          });
        });
      });
    };

    var fetchBlocks= function() {
      $.getJSON(api_url + '/web/currency_info', function(data) {
        currency_info= data;
        $.getJSON(api_url + '/recent_blocks', function(data) {
          if(data) recent_blocks= data;
          $(document).trigger('update_blocks');
        });
      });
    }

    var fetchGraph= function(interval) {
      var graph_hashrate= [], graph_doa_hashrate= [], graph_blocks= [];

      $.getJSON(api_url + '/web/graph_data/local_hash_rate/last_' + interval
        ,function(data) {
        $.each(data, function(key, value) {
          el= []; el.push(parseInt(value[0]) * 1000,
            parseFloat(value[1]));
          graph_hashrate.push(el);
        });
        graph_hashrate.sort();
        $.getJSON(api_url + '/web/graph_data/local_dead_hash_rate/last_' + interval
          ,function(data) {
          $.each(data, function(key, value) {
            el= []; el.push(parseInt(value[0]) * 1000,
              parseFloat(value[1]));
            graph_doa_hashrate.push(el);
          });
          graph_doa_hashrate.sort();
          if (typeof recent_blocks == 'undefined') { 
            // init fetchBlocks() has not finished. Need to fetch it myself.

            $.getJSON(api_url + '/recent_blocks'
              ,function(data) {
              $.each(data, function(key, block) {
                el= []; el.push(parseInt(block["ts"]) * 1000);
                graph_blocks.push(el);
	      });
              draw(graph_hashrate, graph_doa_hashrate, graph_blocks, 'chart', interval);
            });
          } else if (recent_blocks) {
            // init fetchBlocks() has finished.

            $.each(recent_blocks, function(key, block) {
              el= []; el.push(parseInt(block["ts"]) * 1000);
                graph_blocks.push(el);
            });
            draw(graph_hashrate, graph_doa_hashrate, graph_blocks, 'chart', interval);
          } else {
            // init fetchBlocks() has finished, but there are no recent blocks.

            draw(graph_hashrate, graph_doa_hashrate, graph_blocks, 'chart', interval);
          }
        });
      });
    };

    // Let the GitHub ribbon fade out and be removed after 5 seconds.

    if(config.show_github_ribbon) {
      setTimeout(function() {
        $('#ribbon').fadeOut(1000, function() {
          this.remove();
        });
      }, 5 * 1000);
    }

    // update tables and miner data

    setInterval(function() {
      $(document).trigger('update');
    }, config.reload_interval * 1000);

    // update blocks and graph

    setInterval(function() {
      $(document).trigger('update_graph');
    }, config.reload_chart_interval * 1000);

    </script>
  </body>
</html>
